package com.google.zxing.client.ohos.camera;

import com.asher.zxingmodule.BaseAbility;
import com.google.zxing.*;
import com.google.zxing.client.ohos.decode.DecodeFormatManager;
import com.google.zxing.common.HybridBinarizer;
import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;
import ohos.eventhandler.InnerEvent;
import ohos.media.image.ImageSource;
import ohos.media.image.PixelMap;
import ohos.media.image.common.Size;

import java.util.*;

public class DecodeHandler extends EventHandler {
    public static final int RECIVEIMAGE = 10;
    public BaseAbility ability;

    private final MultiFormatReader multiFormatReader;
    private final Map<DecodeHintType,Object> hints =  new EnumMap<>(DecodeHintType.class);

    public DecodeHandler(EventRunner runner, BaseAbility ability) throws IllegalArgumentException {
        super(runner);
        this.ability = ability;
        initHints();
        multiFormatReader = new MultiFormatReader();
        multiFormatReader.setHints(hints);
    }

    private void initHints() {
        Collection<BarcodeFormat> decodeFormats = EnumSet.noneOf(BarcodeFormat.class);
        decodeFormats.addAll(DecodeFormatManager.PRODUCT_FORMATS);
        decodeFormats.addAll(DecodeFormatManager.INDUSTRIAL_FORMATS);
        decodeFormats.addAll(DecodeFormatManager.QR_CODE_FORMATS);
        decodeFormats.addAll(DecodeFormatManager.DATA_MATRIX_FORMATS);
        decodeFormats.addAll(DecodeFormatManager.AZTEC_FORMATS);
        decodeFormats.addAll(DecodeFormatManager.PDF417_FORMATS);
        hints.put(DecodeHintType.POSSIBLE_FORMATS, decodeFormats);
    }

    @Override
    protected void processEvent(InnerEvent event) {
        super.processEvent(event);
        switch (event.eventId){
            case RECIVEIMAGE:
                int widht = event.getPacMap().getIntValue("width");
                int height = event.getPacMap().getIntValue("height");
                decode((byte[]) event.object, widht, height);
                break;

        }
    }


    /**
     * Decode the data within the viewfinder rectangle, and time how long it took. For efficiency,
     * reuse the same reader objects from one decode to the next.
     *
     * @param data   The YUV preview frame.
     * @param width  The width of the preview frame.
     * @param height The height of the preview frame.
     */
    private void decode(byte[] data, int width, int height) {
        Result rawResult = null;
        PlanarYUVLuminanceSource source = null;
        if (ability.getCameraManager() != null){
            source = ability.getCameraManager().buildLuminanceSource(data,width,height);
        }else{
            source = new PlanarYUVLuminanceSource(data, width, height, 0, 0,width, height, false);
        }

        if (source != null) {
            BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
            try {
                rawResult = multiFormatReader.decodeWithState(bitmap);
            } catch (ReaderException re) {
                // continue
            } finally {
                multiFormatReader.reset();
            }
        }

        EventHandler handler = ability.getAbilityHandler();
        if (rawResult != null) {
            // Don't log the barcode contents for security.
            if (handler != null) {
                InnerEvent innerEvent = InnerEvent.get(ScanAbilityHandler.DECALDSUCCESS);
                innerEvent.object = rawResult;
                ability.getAbilityHandler().sendEvent(innerEvent);
            }
        } else {
            if (handler != null) {
                InnerEvent innerEvent = InnerEvent.get(ScanAbilityHandler.DECALDFAIL);
                innerEvent.object = rawResult;
                ability.getAbilityHandler().sendEvent(innerEvent);
            }
        }
    }

    private void bundleThumbnail(PlanarYUVLuminanceSource source) {
        int[] pixels = source.renderThumbnail();
        int width = source.getThumbnailWidth();
        int height = source.getThumbnailHeight();
        ImageSource.SourceOptions opts = new ImageSource.SourceOptions();
        opts.formatHint = "image/png";
        ImageSource imageSource = ImageSource.create(source.getMatrix(), opts);
        ImageSource.DecodingOptions decodingOpts = new ImageSource.DecodingOptions();
        decodingOpts.desiredSize = new Size(width, height);
        PixelMap bitmap = imageSource.createPixelmap(decodingOpts);
        ability.setResultPixelMap(bitmap);
//        ByteArrayOutputStream out = new ByteArrayOutputStream();
    }
}
